# 注释

name = '菜菜'  # 变量
print(name)   # 输出
print(type(name))   # 查看变量的数据类型

age = 18
print('我今年%d' % age)
print('我叫%s，今年%d' % (name, age))   # 多个变量% （变量1，变量2，变量。。。。） 括号括起来，逗号隔开
print(f'我的名字是{name}，我今年{age}了')  # 多个变量 f'....{变量1}，...{变量2}...' f加单引号，中间变量用花括号引起来

width = 47.5
print('我的体重是%f' % width)
print('我的体重是%.2f' % width)   # %.xf 保留x位小数
stu_id = 87
print('我的学号是%06d' % stu_id)   # %0xd 整数x位输出，不足x位0补全，超出x位原样输出

print(' hello \n python')    # \n 换行
print('\t hello\t python')    # \t tab键

print('hhhhhh我是hhhhh', end="\n")   # end结束符
print('ccccc我是cccc', end="123456")
print('aaaa')

# 数据类型转换
num = 12   # 整数
num_f = 16.0   # 小数
str_num = '18'  # 字符串
list_num = [1, 2, 3]  # 列表
tuple_num = (4, 5, 6)  # 元组
set_num = {7, 8, 9}   # 集合
dict_num = {'num': '18', age: 15}   # 字典

# 将数据转换成整数
print(int(num_f), type(int(num_f)))
# 将数据转换成字符串
print(str(num), type(str(num)))
# 将数据转换成小数
print(float(num), type(float(num)))
# 将数据转换成元组
print(tuple(list_num))
# 将数据转换成列表
print(list(tuple_num))
# 将数据转换成原本de数据类型
print(eval(str_num), type(eval(str_num)))

# 逻辑运算符 and or not 与或非
a = 10
b = 20
print((a > 0) and (b > a))   # true
print((a < 0) or (b < 0))   # false
print(not (a > 0))   # false

# and or 数字运算
c = 0
print(a and b, a and c)   # 20 0   不为0返回第二个数
print(a or b, b or c, c or c)  # 10 20 0 不为0返回第一个数

# if语句
# age = int(input("请输入年龄："))   # 输入de是字符串 需要转成整数
# # if (age > 18) and (age < 30):
# if 18 <= age < 30:      # 更简单写法
#     print('你成年啦！')
# elif age > 30:
#     print('你应该成家啦！')
# else:
#     print('你还未成年！')

# import 可以导入模块 这里导入随机数模块
import random

num = random.randint(0, 2)   # 产生0 - 2 的随机整数
print('随机数是：%d' % num)

# 三元表达式
a = 1
b = 2
c = a if a > b else b  # 条件成立返回a c=a，条件不成立返回b，c=b
print(c)   # 2

# while循环
i = 1
result = 0
while i <= 100:
    result += i
    i += 1
print(result)    # 5050

result2 = 0
i = 1
while i <= 100:
    if i % 2 == 0:   #偶数相加
        result2 += i
    i += 1
print(result2)  # 2550

# 9*9乘法表
i = 1
while i<=9:
    j = 1
    while j<=i:
        print(f'{j} * {i} = {j*i}', end='\t')
        j += 1
    print()
    i += 1

# 切片 选取想要的数据
str1 = '0123456789'
print(str1[1:7:1])   # 从下标1开始，到下标7位置（不包括下标7的数据），每间隔1取一个数据
print(str1[1:7:2])
print(str1[7:1:-1])   # 步长可以是负数，也可以不写，默认为1

# 字符串查找
str2 = 'abc hello and bca and abc and cdb'
# find查找
print(str2.find('abc'))  # 下标0
print(str2.find('abc',10,30))  # 从下标10-30中间查找子串
print(str2.find('aaaaaa'))  # 不存在返回-1

# index查找
print(str2.index('and'))  # 下标0
print(str2.index('and',10,30))  # 从下标10-30中间查找子串
# print(str2.index('aaaaaa'),'不存在')  # 不存在返回报错

# count计算子串出现的次数
print(str2.count('and'))  #3次
print(str2.count('and',10,30))  # 从下标10-30中间查找子串
print(str2.count('aaaaaa'))  # 不存在返回0

# 字符串代替 replace
print(str2.replace('and', 'he'))  # 将字符串中的and替换成he，返回值是新的字符串
print(str2.replace('and', 'he', 2))  # 替换2次

# 字符串分割 split
print(str2.split('and'))   # 将字符串根据and进行分割，返回值是一个字符串序列
print(str2.split('and', 2))   # 分割次数

# 字符串连接 join
str3 = ['abc', 'bcd', 'efg']
print('...'.join(str3))   # 将字符串序列通过‘...’连接成一个新的字符串，返回值是新的字符串

# 字符串第一个字母大写，其他小写 capitalize
print(str2.capitalize())
# 字符串每个单词首字母大写 title
print(str2.title())
# 将字符串中的小写字母转成大写 upper
print(str2.upper())
# 将字符串中的大写字母转成小写 lower
print(str2.lower())

str4 = '  abcdef 123 ghijk 456 opq  '
# 去除字符串两侧的空格 strip 去除右侧空格rstrip
print('*' + str4.strip() + '*')
# 去除左侧空格lstrip
print('*' + str4.lstrip() + '*')
# 去除右侧空格rstrip
print('*' + str4.rstrip() + '*')

str5 = 'hello'
print(str5.ljust(10,'.'))  # 左对齐字符串，10个字符，不足10个.补充
print(str5.rjust(10,'.'))  # 右对齐字符串，10个字符，不足10个.补充
print(str5.center(11))   # 在11个字符之间居中对齐

str6 = 'hello world python'
print(str6.startswith('hello')) # true 判断字符串是否以hello开头，返回值是true或false
print(str6.endswith('on')) # true 判断字符串是否以on结尾，返回值true或false
print(str6.isalpha())   # false 判断字符串是否全为字母（不能有空格），返回值true或false
print(str6.isdigit())  # false 判断字符串是否全为数字（不能有空格），返回值true或false
print(str6.isalnum())  # false 判断字符串是否由数字/字母组成（不能有空格），返回值true或false
print(str6.isspace())  # false 判断字符串是否全为空格，返回值true或false


# 列表
list1 = ['caicai', 'miaomiao', 'gege']
print(list1.index('caicai'))  # 0 查看下标
print(list1.count('gege'))  # 1 查看出现de次数
print('miao' in list1)  # false 判断列表中是否有miao
print('miao' not in list1)  # true 判断列表中是否欸没有miao
list1[1] = 'ainiya'
print(list1)

list2 = [1, 7, 5]
list2.append(9)   # 在列表末尾添加新数据
print(list2)
list2.append([123,456])   # 在列表末尾添加新数据 数据为一整个列表
print(list2)
list2.extend([1,22,33])   # 在列表末尾添加新数据 拆分序列加入
print(list2)

list2.insert(5,'caicai')   # 在指定下标位置添加新数据
print(list2)

# 删除数据
# del list2  # 删除整个列表
del list2[4]    # 删除指定下标数据
print(list2)

list2.pop(3)  # 删除指定下标数据  不写默认删除最后一个
print(list2)

list2.remove('caicai')  # 删除指定数据
print(list2)

list2.reverse()  # 逆序排序
print(list2)
list2.sort()   # 升序排序
print(list2)
list2.sort(reverse=True)   # 降序排序
print(list2)

# 列表复制
list3 = list2.copy()  # 复制列表
print(list3)

# 列表循环
i = 0
while i < len(list3):
    print(list3[i], end=',')
    i += 1
print()

i = 0
for i in list3:
    print(i, end=',')  # 此时i就是列表中的数据
    i += 1
print()

import random
# 综合练习
# 有8个人 3个办公室 随机分配人数
teachers = ['小A', '小B', '小C', '小D', '小E', '小F', '小G', '小H']
offices = [[], [], []]  # 三个办公室
for name in teachers:
    num = random.randint(0, 2)  # 产生0 1 2三个随机数，代表三个办公室
    # append（用这个） extend insert
    offices[num].append(name)   # 把老师名字加入对应办公室中

i = 1
for off in offices:
    print(f'办公室{i}的人数是：{len(off)},分别是：')
    for name in off:
        print(name,end=',')
    print()

# 字典 dict
dict1 = {'name':'caicai','age':18,'sex':'女'}
print(dict1.get('name'))   # caicai 返回属性的值，
print(dict1.get('names'))  # None 属性不存在返回None
print(dict1.get('names', 'miaoge'))  # miaoge 属性不存在返回,有第二个参数返回第二个参数的值

print(dict1.keys())  # dict_keys(['name', 'age', 'sex']) 返回包含所有属性的一个可迭代的对象
print(dict1.values())  # dict_values(['caicai', 18, '女']) 返回包含所有属性值的一个可迭代的对象
print(dict1.items())   # dict_items([('name', 'caicai'), ('age', 18), ('sex', '女')]) 返回包含所有键值对的一个可迭代的对象

# 字典遍历  --- 属性遍历
dict1 = {'name': 'caicai', 'age': 18, 'sex': '女'}
for key in dict1.keys():  # 循环遍历获取到的所有属性
    print(key, end=',')  # 输出 name,age,sex

for value in dict1.values():  # 循环遍历获取到的所有属性值
    print(value, end=',')  # 输出 caicai,18,女,

for item in dict1.items():  # 循环遍历获取到的所有元素（键值对）
    print(item, end=',')  # 输出 ('name', 'caicai'),('age', 18),('sex', '女')

for key, value in dict1.items():  # 循环遍历获取到的所有元素（键值对）,然后进行拆包
    print(f'{key} = {value}', end=',')  # 输出 name = caicai,age = 18,sex = 女
print()

# 集合 集合中的数据不会重复
set1 = {10, 20, 30, 10, '123'}
print(set1, type(set1))  # {10, 20, 30} <class 'set'>

# 集合 --- 添加数据
set1.add(50)  # add 只能添加单个数据
print(set1)

set1.update([1, 'caicai'])  # update 可以添加多个数据（列表形式）
print(set1)

set1.remove('123')  # 删除指定数据 ，如果数据不存在会报错
print(set1)

set1.discard(10)  # 删除指定数据 ，如果数据不存在也不会报错
print(set1)

num = set1.pop()  # 随机删除集合中的一个数据数据 ，并返回被删除的数据
print(num)
print(set1)

# 公共方法
list1 = [1, 3, 4, 2, 6, 9, 7]
# min方法 获取最小的数据值
print(min(list1))  # 1
# max方法 获取最大的数据值
print(max(list1))  # 9
# len方法 获取存储数据长度
print(len(list1))  # 7
# range方法
for i in range(1, 10, 2):  # 循环遍历range产生的1-9
    print(i, end=',')  # 1,3,5,7,9,
print()
for i in range(1, 10):  # 循环遍历range产生的1-9
    print(i, end=',')  # 1,2,3,4,5,6,7,8,9,
print()
for i in range(10):  # 循环遍历range产生的1-9
    print(i, end=',')  # 0,1,2,3,4,5,6,7,8,9,
print()

list1 = [1, 3, 4, 2]
# enumerate方法 生成索引和数据的元组 第二个参数是索引开始de值，不写默认从0开始
for i in enumerate(list1):
    print(i)
for i in enumerate(list1, 1):
    print(i)

# 函数
# def 定义一个函数
def in_for():
    """ 这里是函数文档说明，in_for函数是输出信息用的"""
    print('你好我是in_for函数')
# 调用函数
in_for()
# 调用函数文档说明help()
help(in_for)

# 带参数的函数
def sum1(a, b):
    print('我是求和函数')
    return a+b  # return返回值
# 调用函数
num = sum1(50, 50)
print(num)

# 不定长参数写法：
def fun1(*args):
    print(args)  # 元组形式输出

fun1('helo', '123', 456)

def fun2(**kwargs):
    print(kwargs)   # 字典形式输出

fun2(name='cai', age=18, city='sz')

# 元组拆包
tuple1 = (1, 5, '菜菜')
a, b ,c = tuple1
print(a, b, c)  # 1 5 菜菜

# 字典拆包
dict1 = {'name':'caicai', 'age':18}
a, b = dict1
print(a, b)  # name age
print(dict1[a], dict1[b]) # caicai 18

# id()函数可以查看变量存储的内存地址
a = 10
b = a  # a 和 b 指向同一个内存数据
print(id(a), id(b))

# 递归 自己调用自己
# 1. 累计n个数以内的累加和
def sum_num(n):
    if n == 1:
        return 1
    else:
        return n + sum_num(n-1)

print(sum_num(6))

# 匿名函数 lambda
def fun1():
    return 100
a = fun1()
print(a)

fun2 = lambda: 'bbbbb'  # 匿名函数无参数 返回bbbbb
print(fun2())

fun3 = lambda a, b: a+b  # 匿名函数带参数
print(fun3(10, 20))

fun4 = lambda a, b, c = 50: a + b + c
print(fun4(10, 20))   # 匿名函数带默认参数值

fun5 = lambda *args: args  # 参数数量不确定 返回元组类型
print(fun5(1, 2, 3))

fun6 = lambda **kwargs: kwargs  # 参数带值 返回字典类型
print(fun6(name='caicai', age=18))

fun7 = lambda a, b: a if a > b else b # 带if
print(fun7(1,10))

list1 = [{'name': 'caicai', 'age':13},
         {'name': '喵喵', 'age':17},
         {'name': 'zhizhi', 'age':16}]
# 利用lambda对列表中的字典中的某个属性进行排序
list1.sort(key=lambda x: x['name'])  # 对name属性进行排序
print(list1)

list1.sort(key=lambda x: x['age'],reverse=True)  # 对age属性进行降序排序
print(list1)


# 高阶函数 ：一个函数作为另一个函数的参数
print(abs(-45), round(5.6))  # abs()求绝对值 round()求四舍五入结果

list1 = [1, 2, 3, 4]
# 内置高阶函数 map（fun，list）
# fun是函数，list是列表，map函数的功能是将函数作用在列表中的每一项，返回一个迭代器，查看结果需要转换成列表
def func(num):
    return num**2
result = map(func,list1)  # 返回结果是迭代器
print(result)  # <map object at 0x0000002C9C43B580> 输出的是内存地址
print(list(result))  # 转换成列表输出

list1 = [1, 2, 3, 4]
# 内置高阶函数reduce（func，list）
# 需要引入函数工具模块functools，func是函数，必须有两个参数，list是列表，reduce函数作用是将list作用函数后的结果于下一项进行累加
import functools
def func(a, b):
    return a + b
result = functools.reduce(func,list1)
print('***',result)

list1 = [1, 2, 3, 4]
# 内置高阶函数filter（func，list）
# 过滤列表中不符合的选项，返回的是一个filter对象，需要通过list（）转换成列表
def func(x):
    return x % 2 == 0
result = filter(func,list1)
print(list(result))



